#pragma once
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
#include <fcntl.h>
#include <jsoncpp/json/json.h>
#include <atomic>
#include <boost/algorithm/string.hpp>
#include <fstream>
namespace ns_util
{
    const std::string temp_path = "./temp/";
    class TimeUtil
    {
    public:
        static std::string getTimestamp()
        {
            struct timeval _time;
            gettimeofday(&_time, nullptr);
            return std::to_string(_time.tv_sec);
        }
        static std::string getMTimestamp()
        {
            struct timeval _time;
            gettimeofday(&_time, nullptr);
            return std::to_string(_time.tv_sec * 1000 + _time.tv_usec / 1000);
        }
    };

    class PathUtil
    {

    public:
        static std::string addSuffix(const std::string &file_name, const std::string &suffix)
        {
            std::string path_name = temp_path;
            path_name += file_name;
            path_name += suffix;
            return path_name;
        }
        static std::string scr(const std::string &file_name)
        {
            return addSuffix(file_name, ".cpp");
        }
        static std::string exe(const std::string &file_name)
        {
            return addSuffix(file_name, ".exe");
        }
        static std::string compileErr(const std::string &file_name)
        {
            return addSuffix(file_name, ".compile_err");
        }

        static std::string stdIn(const std::string &file_name)
        {
            return addSuffix(file_name, ".stdin");
        }
        static std::string stdOut(const std::string &file_name)
        {
            return addSuffix(file_name, ".stdout");
        }
        static std::string stdErr(const std::string &file_name)
        {
            return addSuffix(file_name, ".stderr");
        }
    };
    class FileUtil
    {
    public:
        static bool isFileExists(const std::string &file_name)
        {
            struct stat st;
            if (stat(file_name.c_str(), &st) == 0)
            {
                return true;
            }
            return false;
        }
        static std::string getFileName()
        {
            // 获取毫秒级时间戳
            std::string mt = TimeUtil::getMTimestamp();
            // 获取序列号
            static std::atomic_uint i(0);
            i++;
            std::string unqi_id = std::to_string(i);
            return mt + "_" + unqi_id;
        }
        static bool writeFile(const std::string &file_name, const std::string &content)
        {
            std::ofstream out(file_name);
            if (!out.is_open())
            {
                return false;
            }
            out.write(content.c_str(), content.size());
            out.close();
            return true;
        }
        static bool readFile(const std::string &file_name, std::string *content, bool keep)
        {
            (*content).clear();

            std::ifstream in(file_name);
            if (!in.is_open())
            {
                return false;
            }
            std::string line;
            // getline:不保存行分割符,有些时候需要保留\n,
            // getline内部重载了强制类型转化
            while (std::getline(in, line))
            {
                (*content) += line;
                (*content) += (keep ? "\n" : "");
            }
            in.close();
            return true;
        }

        static bool isFileEmptyBySize(const std::string &file_name)
        {
            std::ifstream in(file_name, std::ios::binary | std::ios::ate);
            if (!in.is_open())
            {
                std::cerr << "无法打开文件: " << file_name << std::endl;
                return true; // 如果无法打开文件，视为空
            }
            // 获取文件大小
            std::streampos fileSize = in.tellg();
            in.close();

            return fileSize == 0;
        }
    };

    class JsonUtil
    {
    public:
        static bool Serialize(const Json::Value &val, std::string &body)
        {
            std::stringstream ss;
            // 实例化工厂
            Json::StreamWriterBuilder swb;
            swb["emitUTF8"] = true;

            std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
            int ret = sw->write(val, &ss);
            if (ret != 0)
            {
                std::cout << "write fail" << std::endl;
                return false;
            }
            body = ss.str();
            return true;
        }

        static bool DeSerialize(const std::string &body, Json::Value &val)
        {
            Json::CharReaderBuilder crb;
            std::string errs;
            std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
            bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), &val, &errs);
            if (ret == false)
            {
                std::cout << "json unserialize failed : " << errs << std::endl;
                return false;
            }
            return true;
        }
    };
    class StringUtil
    {
    public:
        static void splitString(const std::string &in, std::vector<std::string> *out, const std::string &sep)
        {
            boost::algorithm::split(*out, in, boost::algorithm::is_any_of(sep));
        }
    };
}